前情提要
在做kong容器实验的时候,发现kong数据平面默认监听的端口是8000和8443,非常难受。
通过容器启动时声明环境变量的方式,将数据平面监听端口改成了80和443,但是启动时提示[nginx: [emerg] bind() to 0.0.0.0:80 failed (13: permission denied)]
。
在Kong API网关搭建部署记录通过更改配置的方式,可以实现让数据平面监听在80和443,这就有点奇怪了。
于是乎去看了下kong社区是怎么生成容器镜像的,项目地址在这里。
Dockerfile
以alpine为例,找到项目里面的alpine/Dockerfile
文件,内容如下
1 | FROM alpine:3.10 |
可以看到,Kong容器默认运行指令为/docker-entrypoint.sh kong docker-start
Entrypoint
那么来看看docker-entrypoint.sh
里面做了什么事情吧。
1 | !/bin/sh |
从脚本里面可以看到做了以下几个事情
- 判断参数为
docker-start
时,执行kong prepare
- 判断环境变量是否带有
transparent
,有的话就执行setcap cap_net_raw=+ep
,没有就直接结束判断 - 修改
/usr/local/kong
的owner和group - 最终是使用kong用户去启动Nginx进程。
1 | / # ps -ef |
从容器里面可以看到,Nginx进程是以kong用户运行的,自然就没有权限监听小于1024的端口,那么transparent怎么就可以了呢,回到if判断里面执行了setcap cap_net_raw=+ep
这样的命令。
这个cap_net_raw
是干什么用的,查了下文档,针对此项的说明如下
1 | CAP_NET_RAW |
也就是,根据脚本判断到kong需要实现transparent功能时,会给nginx添加CAP_NET_RAW,以实现普通用户也能运行需要trasparent proxying权限的程序。
思考
那么问题来了,在Linux capabilities里面,是否有相关的权限可以让程序绑定小于1024的端口呢。
恩,很好,一下就找到了CAP_NET_BIND_SERVICE,说明如下
1 | CAP_NET_BIND_SERVICE |
魔改
接下来就是魔改entrypoint的节奏了,修改如下
在34行给nginx进程添加了CAP_NET_BIND_SERVICE权限
1 | !/bin/sh |
重新构建容器镜像了
1 | docker build -t newkong:v1 . |
成果检验
重新运行容器
1 | docker run -d \ |
查看日志
1 | docker logs kong |
查看进程
1 | docker exec -it kong /bin/sh -c "ps -ef" |
查看监听
1 | docker exec -it kong /bin/sh -c "netstat -lp" |
可以看到,Nginx已经可以成功监听80和443端口了。欧耶~!
后记
最后琢磨了一下,通过传入启动命令的方式也可以实现kong监听80和443端口。
感觉绕了弯子……
1 | docker run -d \ |